using System.Collections.Generic;
using UnityEngine;

public class Zombie : MonoBehaviour
{
	public string title;

	public Body body;

	public AnimationCurve deployPriority;

	public int deployAfterDay;

	public float health = 100f;

	public float damage = 20f;

	public int money = 2;

	public float speed = 1f;

	public float realSpeed = 1f;

	public bool isDog;

	[Range(0f, 10f)]
	public int deployWeight;

	[Range(0f, 1f)]
	public float vomitChance = 0.1f;

	[Range(1f, 3f)]
	public float speedDeviation = 1.2f;

	public bool isStandable = true;

	public bool isMoveable = true;

	public bool isWeaponKnockbackable = true;

	public bool isAttackable;

	public bool isTouchPlayer;

	public bool isResting;

	public bool isBurning;

	public float flummoxUntil;

	public AnimalTrap animalTrap;

	public Rigidbody2D rb;

	public Collider2D col;

	public Animator animator;

	public float cannotMoveBeforeTime;

	public GameObject attackTarget;

	public float attackSleep = 0.5f;

	public float attackAt = 0.5f;

	public Player player;

	public float playerDistance;

	public float knockbackRestTime;

	public List<GameObject> contactedPlayerObject = new List<GameObject>();

	public List<GameObject> dropWhenDown = new List<GameObject>();

	public GameObject tmpTarget;

	public Vector3 targetPos;

	public float randomSeed;

	private void Start()
	{
		if ((bool)CampaignGame.Instance)
		{
			CampaignGame.Instance.zombies.Add(this);
		}
		randomSeed = Random.value;
		body.health = health;
		body.speed = speed * Random.Range(1f, speedDeviation);
		if ((bool)CampaignGame.Instance)
		{
			body.health *= Mathf.Max(1f, 1f + ((float)CampaignGame.Instance.day - 30f) / 150f);
			damage *= Mathf.Max(1f, 1f + ((float)CampaignGame.Instance.day - 60f) / 200f);
		}
		int num = 19;
		if (player != null && !player.campaignGame.isPlayground && DO.Campaign.day > num)
		{
			float num2 = Mathf.Min(6f, ((float)DO.Campaign.day - (float)num + 1f) / 10f);
			if (num2 > 0f)
			{
				body.speed += num2;
			}
		}
		realSpeed = body.speed;
		SetAnimatorRandomSeed();
		animator.SetFloat("speed", body.speed);
		if ((bool)player)
		{
			body.audioSource.volume = 0f;
		}
		SetVomit();
	}

	public void PlayAudio(AudioClip audio)
	{
		if (!body.isDead)
		{
			body.audioSource.PlayOneShot(audio);
		}
	}

	public void Speak(AudioClip audio)
	{
		if (!body.isDead)
		{
			body.Speak(audio);
		}
	}

	public void SetVomit()
	{
		if ((bool)body.vomitPs)
		{
			if (vomitChance == 0f)
			{
				Object.Destroy(body.vomitPs);
			}
			body.vomitPs.GetComponent<Vomit>().body = body;
			if (vomitChance > 0f && (bool)player)
			{
				Invoke("Vomit", Random.Range(10f, 1f / vomitChance));
			}
		}
	}

	public void Vomit()
	{
		if (body.isDead || !isStandable || base.transform.localScale.x < 0f)
		{
			return;
		}
		if (playerDistance < 8f)
		{
			animator.SetTrigger("vomit");
			foreach (Collider2D collider in player.body.colliders)
			{
				if (collider.name == "ChestRb")
				{
					body.vomitPs.trigger.SetCollider(0, collider);
					break;
				}
			}
		}
		Invoke("Vomit", Random.Range(10f, 1f / vomitChance));
	}

	private void FixedUpdate()
	{
		if (body.isDead)
		{
			return;
		}
		if (!isStandable && isDog)
		{
			body.Die();
		}
		float num = Mathf.Abs(rb.velocity.x);
		animator.SetFloat("velocity", num);
		animator.SetBool("isFlummoxing", flummoxUntil > Time.time);
		if (flummoxUntil > Time.time)
		{
			return;
		}
		if ((bool)player)
		{
			playerDistance = Vector2.Distance(base.transform.position, player.transform.position);
			body.audioSource.volume = (15f - playerDistance) / 15f;
			if (!isStandable && num < 0.3f && !isResting)
			{
				CanMove();
			}
		}
		if ((bool)player && isMoveable && !isTouchPlayer && !animalTrap)
		{
			if (tmpTarget == null)
			{
				targetPos = player.transform.position;
				if (Vector2.Distance(base.transform.position, targetPos) > 5f)
				{
					targetPos.y = base.transform.position.y;
				}
				rb.velocity = (targetPos - base.transform.position).normalized * body.speed;
				animator.SetBool("isAttract", value: false);
			}
			else
			{
				targetPos = tmpTarget.transform.position;
				if (Mathf.Abs(base.transform.position.x - targetPos.x) < 2f && Mathf.Abs(base.transform.position.y - targetPos.y) < 0.5f)
				{
					animator.SetBool("isAttract", value: true);
				}
				else
				{
					animator.SetBool("isAttract", value: false);
					rb.velocity = (targetPos - base.transform.position).normalized * body.speed;
				}
			}
			Vector3 localScale = base.transform.localScale;
			if (targetPos.x > base.transform.position.x)
			{
				localScale.x = -1f;
				base.transform.localScale = localScale;
			}
			else
			{
				localScale.x = 1f;
				base.transform.localScale = localScale;
			}
		}
		if (isTouchPlayer && player.isDead)
		{
			animator.SetBool("isPlayerDead", value: true);
			base.gameObject.layer = 12;
		}
		if (!attackTarget && contactedPlayerObject.Count > 0)
		{
			for (int i = 0; i < contactedPlayerObject.Count; i++)
			{
				if ((bool)contactedPlayerObject[i])
				{
					attackTarget = contactedPlayerObject[i];
					break;
				}
				contactedPlayerObject.RemoveAt(i);
			}
		}
		if (!attackTarget && isAttackable)
		{
			CannotAttack();
		}
	}

	public void Die()
	{
		CampaignGame.Instance.zombies.Remove(this);
		DropItem();
		Object.Destroy(col);
		Object.Destroy(rb);
		Object.Destroy(animator);
		Object.Destroy(base.gameObject, 15f);
		Object.Destroy(this, 15f);
		CampaignGame.zombieKillCount++;
		CampaignGame.Income(body.zombie.money);
	}

	public void SetAnimatorRandomSeed()
	{
		animator.SetFloat("random", Random.Range(0f, 1f));
		animator.SetFloat("randomSpeed", Random.Range(0.8f, 1f));
	}

	public void SetRest()
	{
	}

	public void OnHit(BodyPart bodyPart, Weapon weapon, Vector3 direction, Vector2 contactPoint)
	{
		if (weapon == null || bodyPart.knockbackChance == 0f || knockbackRestTime > Time.time)
		{
			return;
		}
		string text = null;
		float num = weapon.stoppingPower / 700f;
		num += bodyPart.damageShare;
		if (isMoveable)
		{
			if (bodyPart.name == "HeadRb" && Random.Range(0f, 1f) > 0.3f)
			{
				animator.SetTrigger("protectHead");
			}
			if (bodyPart.name == "ChestRb" && Random.Range(0f, 1f) > 0.5f)
			{
				animator.SetTrigger("protectChest");
			}
		}
		if (isWeaponKnockbackable && !animalTrap)
		{
			float num2 = Random.Range(0f, 2f);
			if (bodyPart.knockbackChance + num > num2)
			{
				if (health > 500f)
				{
					text = "knockback";
				}
				else if (bodyPart.name == "CalfRb")
				{
					text = "fallDownFront";
					if ((double)bodyPart.damageShare > 0.1)
					{
						CannotStandUp();
					}
				}
				else if (bodyPart.name == "ChestRb")
				{
					string[] array = new string[3] { "kneelDown", "knockback", "fallDownBack" };
					text = array[Random.Range(0, array.Length)];
				}
				else if (bodyPart.name == "HeadRb")
				{
					string[] array2 = new string[2] { "kneelDown", "fallDownBack" };
					text = array2[Random.Range(0, array2.Length)];
				}
				else
				{
					text = "kneelDown";
				}
				animator.SetTrigger(text);
			}
		}
		float num3 = weapon.stoppingPower;
		if (rb.velocity.x < 0f && text == null)
		{
			num3 *= Mathf.Abs(rb.velocity.x) / 2f * 10f;
		}
		if (text != null)
		{
			num3 *= 1.5f;
		}
		Knockback(num3, text);
	}

	public void Knockback(float power, string animation)
	{
		if (!player)
		{
			return;
		}
		if (animation != null)
		{
			knockbackRestTime = Time.time + 0.3f;
			animator.SetTrigger(animation);
			isResting = true;
			animator.SetBool("isResting", isResting);
			float num = 10f * Random.value;
			if (!CampaignGame.Instance.isPlayground)
			{
				num *= Mathf.Clamp01(10 / DO.Campaign.day);
			}
			Invoke("Wakeup", num);
			CannotMove();
			Speak(body.hurtAudios[Random.Range(0, body.hurtAudios.Length)]);
			if (animation != "knockback")
			{
				DropItem();
			}
		}
		rb.velocity = Vector3.zero;
		rb.AddForce(power * Vector2.right);
	}

	public void DropItem()
	{
		if (dropWhenDown.Count <= 0)
		{
			return;
		}
		foreach (GameObject item in dropWhenDown)
		{
			if ((bool)item)
			{
				item.transform.SetParent(null);
				Rigidbody2D component = item.GetComponent<Rigidbody2D>();
				SpriteRenderer component2 = item.GetComponent<SpriteRenderer>();
				BodyPart component3 = item.GetComponent<BodyPart>();
				if ((bool)component2)
				{
					component2.sortingOrder = -1;
				}
				if ((bool)component)
				{
					component.isKinematic = false;
					component.AddForce(Vector2.right * Random.Range(0.5f, 1f) * 50f);
					component.AddTorque(Random.Range(0.5f, 1f) * 200f);
					Object.Destroy(item.GetComponent<Collider2D>(), 3f);
					Object.Destroy(component, 3f);
					Object.Destroy(item, 20f);
				}
				if ((bool)component3)
				{
					Object.Destroy(component3);
				}
			}
		}
	}

	public void Wakeup()
	{
		if (!body.isDead)
		{
			isResting = false;
			animator.SetBool("isResting", isResting);
		}
	}

	public void CannotStandUp()
	{
		if (isStandable)
		{
			DropItem();
			UnTrapped();
			body.speed = Mathf.Min(realSpeed * 0.5f, 0.5f);
			realSpeed = body.speed;
			if (isStandable)
			{
				body.zombie.animator.SetTrigger("fallDownFront");
			}
			isStandable = false;
			animator.SetBool("isStandable", isStandable);
		}
	}

	public void CanMove()
	{
		base.gameObject.layer = 9;
		isMoveable = true;
		animator.SetBool("isMoveable", isMoveable);
	}

	public void CannotMove()
	{
		base.gameObject.layer = 12;
		isMoveable = false;
		animator.SetBool("isMoveable", isMoveable);
	}

	public void CanAttack()
	{
		isAttackable = true;
		animator.SetBool("isAttackable", value: true);
	}

	public void CannotAttack()
	{
		isAttackable = false;
		animator.SetBool("isAttackable", value: false);
	}

	public void CanWeaponKnockBack()
	{
		isWeaponKnockbackable = true;
		animator.SetBool("isWeaponKnockbackable", value: true);
	}

	public void CannotWeaponKnockBack()
	{
		isWeaponKnockbackable = false;
		animator.SetBool("isWeaponKnockbackable", value: false);
	}

	public void Attack()
	{
		if (attackAt > Time.time || !attackTarget || !isAttackable)
		{
			return;
		}
		attackAt = Time.time + attackSleep;
		Player component = attackTarget.GetComponent<Player>();
		if ((bool)component)
		{
			body.Speak(body.bitAudios[Random.Range(0, body.bitAudios.Length)]);
			component.Hurt(damage);
			if (component.body.armor <= 0f && body.mouth != null)
			{
				GameObject gameObject = Object.Instantiate(body.bitEffect, body.mouth.transform.position, Quaternion.identity);
				gameObject.transform.rotation = body.mouth.transform.rotation;
				ParticleSystem[] componentsInChildren = gameObject.GetComponentsInChildren<ParticleSystem>();
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					ParticleSystem.CollisionModule collision = componentsInChildren[i].collision;
					collision.collidesWith = 1 << body.chest.layer - Ground.groundTotal;
				}
				Object.Destroy(gameObject, 3f);
			}
			if (component.body.backlashDamage > 0f && component.body.backlashChance >= Random.value)
			{
				BodyPart component2 = body.transform.Find("ChestRb").GetComponent<BodyPart>();
				component2.OnHit(component.body.backlashDamage, (component2.transform.position - component.body.transform.position).normalized * Random.Range(100, 500), component2.transform.position);
			}
		}
		else
		{
			Tool component3 = attackTarget.GetComponent<Tool>();
			if ((bool)component3 && component3.placed)
			{
				component3.Hurt(damage);
			}
		}
	}

	private void OnCollisionEnter2D(Collision2D collision)
	{
		CheckCatchPlayer(collision.gameObject);
	}

	private void OnTriggerEnter2D(Collider2D collision)
	{
		CheckCatchPlayer(collision.gameObject);
	}

	private void OnCollisionExit2D(Collision2D collision)
	{
		CheckReleasePlayer(collision.gameObject);
	}

	private void OnTriggerExit2D(Collider2D collision)
	{
		CheckReleasePlayer(collision.gameObject);
	}

	public void CheckCatchPlayer(GameObject other)
	{
		if (other.tag == "Player")
		{
			contactedPlayerObject.Add(other);
			attackTarget = other;
			CanAttack();
			if ((bool)other.GetComponent<Player>())
			{
				Wakeup();
				isTouchPlayer = true;
				player.zombieContactCount++;
				animator.SetBool("isTouchPlayer", isTouchPlayer);
			}
		}
	}

	public void CheckReleasePlayer(GameObject other)
	{
		if (other.tag == "Player")
		{
			contactedPlayerObject.Remove(other);
			attackTarget = other;
			CannotAttack();
			if ((bool)other.GetComponent<Player>())
			{
				isTouchPlayer = false;
				player.zombieContactCount--;
				animator.SetBool("isTouchPlayer", isTouchPlayer);
			}
		}
	}

	public void Trapped(AnimalTrap animalTrap)
	{
		this.animalTrap = animalTrap;
		rb.velocity = Vector2.zero;
		rb.isKinematic = true;
		col.isTrigger = true;
		animator.SetBool("isTrapped", value: true);
	}

	public void UnTrapped()
	{
		if ((bool)animalTrap)
		{
			animalTrap.trappedZombie = null;
			animalTrap = null;
			rb.isKinematic = false;
			col.isTrigger = false;
			rb.velocity = Vector2.zero;
			animator.SetBool("isTrapped", value: false);
		}
	}

	private void OnDestroy()
	{
		if ((bool)CampaignGame.Instance)
		{
			CampaignGame.Instance.zombies.Remove(this);
		}
	}
}
